﻿using OSGeo.OGR;
using OSGeo.OSR;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyCustomTool
{
    /// <summary>
    /// shp文件实体类
    /// </summary>
    internal class FileShp
    {
        /// <summary>
        /// 数据源
        /// </summary>
        public DataSource DataSource = null;

        /// <summary>
        /// 图层
        /// </summary>
        public Layer Layer = null;

        /// <summary>
        /// 投影信息
        /// </summary>
        public SpatialReference Spatial;

        /// <summary>
        /// 属性表
        /// </summary>
        public FeatureDefn FeatureDefn = null;

        /// <summary>
        /// 要素总数
        /// </summary>
        public long FeatureCount = 0;

        /// <summary>
        /// 属性表表头
        /// </summary>
        public List<FieldDefn> FieldHead = new List<FieldDefn>();

        /// <summary>
        /// 属性表信息
        /// </summary>
        public List<String> FieldInfo = new List<String>();

        /// <summary>
        /// 几何信息
        /// </summary>
        public Geometry Geometry = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public FileShp() { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="inputFile">数据源文件类</param>
        public FileShp(string path, FileShp inputFile)
        {
            if (File.Exists(path))
            {
                Read(path);
            }
            else
            {
                Create(path, inputFile);
            }
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="path">文件路径</param>
        public void Read(string path)
        {
            // 打开数据
            DataSource = Ogr.Open(path, 1);// 0是只读，1是读写

            // 获取图层
            Layer = DataSource.GetLayerByIndex(0);

            // 获取投影信息
            Spatial = Layer.GetSpatialRef();

            // 获取要素总数
            FeatureCount = Layer.GetFeatureCount(0);

            // 获取属性表表头
            FeatureDefn = Layer.GetLayerDefn();
            for (int i = 0; i < FeatureDefn.GetFieldCount(); i++)
            {
                FieldHead.Add(FeatureDefn.GetFieldDefn(i));
            }
        }

        /// <summary>
        /// 获取要素信息
        /// </summary>
        /// <param name="index">要素索引</param>
        public void GetFeatureData(long index)
        {
            // 获取要素
            Feature feature = Layer.GetFeature(index);

            // 初始化字段存储
            FieldInfo.Clear();
            Geometry = null;

            // 获取要素中的属性表内容
            for (int field = 0; field < FieldHead.Count; field++)
            {
                FieldDefn fieldDefn = FeatureDefn.GetFieldDefn(field);
                FieldType type = fieldDefn.GetFieldType();

                string info;
                switch (type)
                {
                    case FieldType.OFTString:
                        info = feature.GetFieldAsString(field);
                        break;
                    case FieldType.OFTReal:
                        info = feature.GetFieldAsDouble(field).ToString();
                        break;
                    case FieldType.OFTInteger:
                        info = feature.GetFieldAsInteger(field).ToString();
                        break;
                    default:
                        info = feature.GetFieldAsString(field);
                        break;
                }

                FieldInfo.Add(info);
            }

            // 获取要素中的几何体
            Geometry = feature.GetGeometryRef();
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="fieldHead">属性表表头</param>
        public void Create(string path, FileShp inputFile)
        {
            // 注册驱动
            Driver driver = Ogr.GetDriverByName("ESRI Shapefile");

            // 创建数据
            DataSource = driver.CreateDataSource(path, null);

            // 创建图层
            Layer = DataSource.CreateLayer("Output", inputFile.Spatial, inputFile.Layer.GetGeomType(), null);

            // 属性表表头
            FieldHead = inputFile.FieldHead;
            for (int i = 0; i < FieldHead.Count; i++)
            {
                FieldDefn fieldDefn = new FieldDefn(FieldHead[i].GetName(), FieldHead[i].GetFieldType());
                fieldDefn.SetWidth(FieldHead[i].GetWidth());
                Layer.CreateField(FieldHead[i], i);
            }
        }

        /// <summary>
        /// 设置属性表信息
        /// </summary>
        /// <param name="info">属性表信息</param>
        public void SetFeatureData(List<String> info, Geometry geometry)
        {
            // 创建要素
            FeatureDefn = Layer.GetLayerDefn();
            Feature feature = new Feature(FeatureDefn);

            // 添加属性表
            for (int field = 0; field < FieldHead.Count; field++)
            {
                FieldDefn fieldDefn = FeatureDefn.GetFieldDefn(field);
                FieldType type = fieldDefn.GetFieldType();

                switch (type)
                {
                    case FieldType.OFTString:
                        feature.SetField(field, info[field]);
                        break;
                    case FieldType.OFTReal:
                        feature.SetField(field, info[field]);
                        break;
                    case FieldType.OFTInteger:
                        feature.SetField(field, info[field]);
                        break;
                    default:
                        feature.SetField(field, info[field]);
                        break;
                }
            }

            // 添加图形
            feature.SetGeometry(geometry);

            // 添加要素
            Layer.CreateFeature(feature);
        }
    }
}
